#!/usr/bin/env python
'''


    My tools to ease things.

    Usage like the manage.py script

'''

import sys, os

if 'DJANGO_SETTINGS_MODULE' not in os.environ:
    print '#####', os.path.abspath(__file__)
    sys.path.append(os.path.dirname(os.path.abspath(__file__)))
    os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
else:
    print 'Using setting module from ENV:', os.environ['DJANGO_SETTINGS_MODULE']

import django.contrib.auth.models
from django.core.exceptions import ObjectDoesNotExist
import TasK.models

PROGNAME = sys.argv[0]


def _get_group(groupName):
    '''
    Return the user group named groupName, creating it if needed.
    '''
    try:
        group = django.contrib.auth.models.Group.objects.get(name=groupName)
        print 'Retreiving', groupName, 'group.'
    except django.contrib.auth.models.Group.DoesNotExist:
        print 'Init', groupName, 'group.'
        group = django.contrib.auth.models.Group(name=groupName)
        group.save()
    return group

def _get_superuser(login, group=None):
    '''
    Return the super user named login.
    
    If the user does not exist, it is created and added to the 
    given django.contrib.auth.models.Group object 'group'.
    In this case, if groupName is None, a django.contrib.auth.models.User.DoesNotExist
    error is raised.
    
    If the user already exists, it might not be a super user...
    '''
    try:
        user = django.contrib.auth.models.User.objects.get(username=login)
        print 'Retreiving user', login
    except django.contrib.auth.models.User.DoesNotExist:
        if group is None:
            raise
        print 'Creating', group.name, 'user:', login
        user = django.contrib.auth.models.User.objects.create_superuser(login, login+'@macguff.fr', login)
        user.groups.add(group)
    return user

def _get_user(login, group=None):
    '''
    Return the user named login.
    
    If the user does not exist, it is created and added to the 
    given django.contrib.auth.models.Group object 'group'.
    In this case, if groupName is None, a django.contrib.auth.models.User.DoesNotExist
    error is raised.
    '''
    try:
        user = django.contrib.auth.models.User.objects.get(username=login)
        print 'Retreiving user', login
    except django.contrib.auth.models.User.DoesNotExist:
        if group is None:
            raise
        print 'Creating', group.name, 'user:', login
        user = django.contrib.auth.models.User.objects.create_user(login, login+'@macguff.fr', login)
        user.groups.add(group)
    return user

def init_users():
    '''
    Creates the default users in the DB.
    
    !!! You must have sync'ed the db before using this !!!
    
    Proper usage:
        cd path/to/MgDjango
        /usr/bin/python manage.py syncdb   # You can answer 'no' to super user creation...
        /usr/bin/python tool.py init_users
        
    '''
    # DEV
    print "#-- Init Dev group"
    group = _get_group('Dev')
    devUsers = (
              'dee', 
              'phid',
              'ludo',
              'mel',
              'frantzy',
              'sebastos',
              'tomtom',
              'alec',
    )
    for login in devUsers:
        user = _get_superuser(login, group)
    
    # TD
    print "#-- Init TD group"
    group = _get_group('TD')
    tdUsers = (
              'chex', 
              'flavio',
              'fresh',
              'blue',
    )
    for login in tdUsers:
        user = _get_user(login, group)

def _create_object(model, **kwargs):
    '''
    Create an object if it does no exist yet.
    (The name is used to look for the object and must be given
    in keyword arguments)
    '''
    name = kwargs['name']
    try:
        o = model.objects.get(name=name)
        print 'Retreiving', model._meta.object_name, name
    except ObjectDoesNotExist:
        print 'Creating', model._meta.object_name, 'objects:', name
        o = model.objects.create(**kwargs)
    return o

def load_tasks_data():
    '''
    Create arbitrary TasK data for test purpose.
    '''
    print "#-- Init Tags"
    Tag = TasK.models.Tag
    tag_shadowMap = _create_object(Tag, name='ShadowMap', description="The shadow map system.\nThe goal is to blah blah")
    tag_media = _create_object(Tag, name='Media', description="The in house version control system.")
    tag_vfx = _create_object(Tag, name='Vfx', description="Smoke on the water.")
    tag_atlog = _create_object(Tag, name='Atelier Logiciel', description="Whatever is needed and done by the Dev Team for the Dev Team.")

    print "#-- Init Productions"
    Production = TasK.models.Production
    p_vqr = _create_object(Production, name='vqr', description="La Vache Qui Rit.")
    p_lorax = _create_object(Production, name='Lorax', description="De la cachuette au poil.")
    
    print "#-- Init Chantiers"
    Chantier = TasK.models.Chantier 
    c_mglr = _create_object(Chantier, name="Mglr", description="Everything about MacGuff Ligne Renderer.")
    c_symbor = _create_object(Chantier, name="Symbor", description="3D UI.")
    c_trukor = _create_object(Chantier, name="Trukor", description="<B>Legacy</B> Compositing tools.")
    c_nuke = _create_object(Chantier, name="Nuke", description="Compositing stuffs.")
    c_ink = _create_object(Chantier, name="InK", description="Asset management for the masses.")
    c_hou = _create_object(Chantier, name="Houdini", description="Smoke it baby!.")
    c_retd = _create_object(Chantier, name="R&D", description="The Dev is a Dev for the Dev.")

    print "#-- Init Fonctionalites"
    Fonctionalite = TasK.models.Fonctionalite 
    f_houProj = _create_object(Fonctionalite, chantier=c_hou, name="Houdini Integration", description="Let us use this masterpiece software.")
    f_hou2symb = _create_object(Fonctionalite, chantier=c_hou, name="Symbor Export", description="Blah blah...")
    f_lwp = _create_object(Fonctionalite, chantier=c_ink, name="Link With Prev.", description="Consolidate the link with prev medias and assets.")
    
    print "#-- Init Taches"
    Tache = TasK.models.Tache
    
    t_lwpObsolete = _create_object(Tache,
        fonctionalite=f_lwp,
        name="Consolidate last revision",
        creator="tamere",
        length=3,
        description="For now we need su acces to do this. Find another way to Consolidate last revision when historyLength is reached."
    )
    t_lwpObsolete.tags.add(tag_media)
    t_lwpObsolete.productions.add(p_lorax)

    t_lwpNbLink = _create_object(Tache,
        fonctionalite=f_lwp,
        name="Max number of link",
        creator="tamere",
        length=2,
        description="Find a way to have more than 8 links in a row."
    )
    t_lwpNbLink.tags.add(tag_media)
    t_lwpNbLink.productions.add(p_lorax)

    t_lwpTool = _create_object(Tache,
        fonctionalite=f_lwp,
        name="Consolidate tool",
        creator="tamere",
        length=2,
        description="Create a tool to fix a revision with too many links in a row."
    )
    t_lwpTool.tags.add(tag_media)
    t_lwpTool.productions.add(p_lorax)

    t_h2sUV = _create_object(Tache,
        fonctionalite=f_hou2symb,
        name="PACK need UVs",
        creator="michaelp",
        length=2,
        description="The execAction HoudiniExport does not create UV."
    )
    t_h2sUV.tags.add(tag_vfx)
    t_h2sUV.productions.add(p_lorax)

    t_h2sPart = _create_object(Tache,
        fonctionalite=f_hou2symb,
        name="PACK need partitions",
        creator="michaelp",
        length=2,
        description="The execAction HoudiniExport should create one partition per PrimitiveGroup."
    )
    t_h2sPart.tags.add(tag_vfx)
    t_h2sPart.productions.add(p_lorax)

    t_houProjCreate = _create_object(Tache,
        fonctionalite=f_houProj,
        name="Repo svn + Eclipse Proj",
        creator="dee",
        length=3,
        description="Set up the houdini source repository."
    )
    t_houProjCreate.tags.add(tag_atlog)
    t_houProjCreate.tags.add(tag_vfx)
    t_houProjCreate.productions.add(p_lorax)

    t_houProjRls = _create_object(Tache,
        fonctionalite=f_houProj,
        name="release tools",
        creator="dee",
        length=2,
        description="Add tools needed to release mgl houdini plugins."
    )
    t_houProjCreate.tags.add(tag_atlog)
    t_houProjCreate.tags.add(tag_vfx)
    t_houProjCreate.productions.add(p_lorax)

    t_houProjPy = _create_object(Tache,
        fonctionalite=f_houProj,
        name="Mgl Houdini Python",
        creator="dee",
        length=1,
        description="Add a pytho package to the houdini project."
    )
    t_houProjCreate.tags.add(tag_atlog)

    t_houProjPy = _create_object(Tache,
        fonctionalite=f_houProj,
        name="mghou.chache",
        creator="dee",
        length=2,
        description="Create python module mghou.cache to deal with cache paths and automation."
    )
    t_houProjCreate.tags.add(tag_atlog)
    t_houProjCreate.tags.add(tag_vfx)
    t_houProjCreate.productions.add(p_lorax)

def dump_to_python(filename=None):
    '''
    Dumps the TasK data to a python script.
    If filename is not given, an /tmp/ file will be
    created.
    '''
    print 'Init dump'
    buff = []
    
    buff.append("""
'''

    This script has been generated by MgDjango's tool.dump_to_python() function.
    on <date here>

'''

    """)
    buff.append("import datetime")
    buff.append("import django.contrib.auth.models")
    buff.append("import TasK.models")
    
    print 'Dumping tools'
    buff.append('')
    buff.append('#--- TOOLS')
    buff.append('')
    import inspect
    buff.append( inspect.getsource(_create_object) )
    buff.append('')
    #buff.append( inspect.getsource(_get_group) )
    #buff.append('')
    buff.append( inspect.getsource(_get_user) )
    buff.append('')
    buff.append('#--- DATA')
    buff.append('')
          
    print 'Dumping Tags'
    buff.append('print "#--- Init Tags"')
    for tag in TasK.models.Tag.objects.all():
        buff.append('tag_'+`tag.pk`+' = _create_object(')
        buff.append('    TasK.models.Tag,')
        buff.append('    name='+`tag.name`+',')
        buff.append('    description='+`tag.description`+',')
        buff.append(')')
        buff.append('')
    buff.append('')

    print 'Dumping Productions'
    buff.append('print "#--- Init Productions"')
    for prod in TasK.models.Production.objects.all():
        buff.append('p_'+`prod.pk`+' = _create_object(')
        buff.append('    TasK.models.Production,')
        buff.append('    name='+`prod.name`+',')
        buff.append('    description='+`prod.description`+',')
        buff.append(')')
        buff.append('')
    buff.append('')

    print 'Dumping Cahntiers'
    buff.append('print "#--- Init Chantiers"')
    for chan in TasK.models.Chantier.objects.all():
        buff.append('c_'+`chan.pk`+' = _create_object(')
        buff.append('    TasK.models.Chantier,')
        buff.append('    name='+`chan.name`+',')
        buff.append('    description='+`chan.description`+',')
        buff.append(')')
        buff.append('')
    buff.append('')
    
    print 'Dumping Fonctionalites'
    buff.append('print "#--- Init Fonctionalites"')
    for chan in TasK.models.Chantier.objects.all():
        for func in chan.fonctionalite_set.all():
            buff.append('f_'+`func.pk`+' = _create_object(')
            buff.append('    TasK.models.Fonctionalite,')
            buff.append('    chantier=c_'+`chan.pk`+',')
            buff.append('    name='+`func.name`+',')
            buff.append('    description='+`func.description`+',')
            buff.append(')')
            buff.append('')
    buff.append('')

    print 'Dumping Taches'
    buff.append('print "#--- Init Taches"')
    for func in TasK.models.Fonctionalite.objects.all():
        for tache in func.tache_set.all():
            buff.append('t_'+`tache.pk`+' = _create_object(')
            buff.append('    TasK.models.Tache, ')
            buff.append('    fonctionalite=f_'+`func.pk`+', ')
            buff.append('    name='+`tache.name`+',')
            buff.append('    creator='+`tache.creator`+',')
            buff.append('    create_date='+`tache.create_date`+',')
            buff.append('    length='+`tache.length`+',')
            buff.append('    status='+`tache.status`+',')
            buff.append('    start_date='+`tache.start_date`+',')
            buff.append('    priority='+`tache.priority`+',')
            buff.append('    description='+`tache.description`+',')
            buff.append(')')
            for tag in tache.tags.all():
                buff.append('t_'+`tache.pk`+'.tags.add(tag_'+`tag.pk`+')')
            for prod in tache.productions.all():
                buff.append('t_'+`tache.pk`+'.productions.add(p_'+`prod.pk`+')')
            for tdt in tache.tachedevtime_set.all():
                buff.append('if not TasK.models.TacheDevTime.objects.filter(tache=t_'+`tache.pk`+',dev=_get_user('+`tdt.dev.username`+')).exists():') 
                buff.append('    tdt = TasK.models.TacheDevTime(')
                buff.append('        tache=t_'+`tache.pk`+',')
                buff.append('        dev=_get_user('+`tdt.dev.username`+'),')
                buff.append('        time='+`tdt.time`+',')
                buff.append('    )')
                buff.append('    tdt.save()')
            buff.append('')
    buff.append('')

    print 'Dumping Cycles'
    buff.append('print "#--- Init Cycles"')
    for cycle in TasK.models.Cycle.objects.all():
        buff.append('c_'+`cycle.pk`+' = _create_object(')
        buff.append('    TasK.models.Cycle, ')
        buff.append('    name='+`cycle.name`+',')
        buff.append('    start_date='+`cycle.start_date`+',')
        buff.append('    end_date='+`cycle.end_date`+',')
        buff.append('    status='+`cycle.status`+',')
        buff.append('    comments='+`cycle.comments`+',')
        buff.append(')')
        for tdc in cycle.tachesducycle_set.all():
            buff.append('tdc = TasK.models.TachesDuCycle(')
            buff.append('    cycle=c_'+`tdc.cycle.pk`+',')
            buff.append('    tache=t_'+`tdc.tache.pk`+',')
            buff.append('    priority='+`tdc.priority`+',')
            buff.append(')')
            buff.append('tdc.save()')
        buff.append('')
    buff.append('')

    OUT = filename or '/tmp/TasK_dump.py'
    with open(OUT, 'w') as w:
        w.write('\n'.join(buff))
    print 'Script saved to', OUT

def load_dump(filename):
    '''
    Load data from a file created by the dump_to_python() function.
    '''
    execfile(filename)
    
def init_all():
    '''
    Init users and load Tasks data.
    '''
    initusers()
    load_tasks_data()
    
def help(funcName=None):
    '''
    Get help on a tool. 
    '''
    for n, o in globals().iteritems():
        if n.startswith('_'):
            continue
        if callable(o):
            print n+':',
            if o.__doc__:
                print o.__doc__
            else:
                print ''
            
            
if __name__ == '__main__':
    argv = list(sys.argv)
    # pop the program name:
    argv.pop(0)
    # get the func name
    func = argv.pop(0)
    # get the func args as string:
    args = ", ".join([`v` for v in argv])
    
    code = func+'('+args+')'
    print '#--- Executing command:', code
    exec(code)
        

